import {readFileSync} from 'fs';
import {resolve} from 'path';

const isCheckDemo1 = /^<Demo (.*)><\/Demo>$/;
const isCheckDemo2 = /^<Demo (.*) \/>$/;

/** 源码 => 代码块 */
const transformHighlightCode = (mdInstance, sourceCode, suffix) => {
  return mdInstance.options.highlight(sourceCode, suffix, '');
};

/** 注入 script 脚本 引入组件 */
const injectComponentImportScript = function (env, path, componentName) {
  let contentStripped = `import ${componentName} from "${path}";`;
  const setupIndex = env.sfcBlocks.scripts.findIndex(item => item.tagOpen.includes('setup'));
  if (setupIndex !== -1) {
    contentStripped = env.sfcBlocks.scripts[setupIndex].contentStripped + contentStripped;
    env.sfcBlocks.scripts[setupIndex] = {
      type: 'script',
      tagClose: '</script>',
      tagOpen: "<script setup lang='ts'>",
      content: `<script setup lang="ts">${contentStripped}</script>`,
      contentStripped
    };
  } else {
    env.sfcBlocks.scripts.push({
      type: 'script',
      tagClose: '</script>',
      tagOpen: "<script setup lang='ts'>",
      content: `<script setup lang="ts">${contentStripped}</script>`,
      contentStripped
    });
  }
};

/** 获取组件传参 */
const getProps = (str: string) => ({path: str.match(/path="(.*?)"/)?.[1] || ''});

const transformPreview = function (md, token, env) {
  const componentProps = getProps(token.content);
  /** 组件绝对路径 */
  // const componentPath = resolve(env.path, '../', componentProps.path || '.');
  const componentPath = resolve(env.path, '../../../../src/', componentProps.path || '.');
  /** 后缀名 */
  const suffixName = componentPath.split('.').at(-1);
  /** 组件名 */
  const componentName = componentProps.path.split('/').at(-1)?.replace('.vue', '');
  // 注入组件导入语句
  injectComponentImportScript(env, componentProps.path, componentName);
  /** 组件源码 */
  const componentSourceCode = readFileSync(componentPath, {encoding: 'utf-8'});
  /** 高亮显示源码 */
  const compileHighlightCode = transformHighlightCode(md, componentSourceCode, suffixName);
  const code = encodeURIComponent(componentSourceCode);
  const showCode = encodeURIComponent(compileHighlightCode);
  const link = componentProps.path.replace('.vue', '');

  return `<Demo path="${link}" showCode="${showCode}" code="${code}"> <${componentName} /> </Demo>`;
};

export const mdPlugin = (md: any) => {
  const defaultHtmlInlineRender = md.renderer.rules.html_inline;
  md.renderer.rules.html_inline = function (tokens, idx, options, env, self) {
    const token = tokens[idx];
    if (isCheckDemo1.test(token.content) || isCheckDemo2.test(token.content)) {
      return transformPreview(md, token, env);
    }
    return defaultHtmlInlineRender(tokens, idx, options, env, self);
  };
};
